package org.common.utils;


import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassScannerUtils {

    public static Set<Class<?>> getClasses(String packageName) throws IOException, ClassNotFoundException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        assert classLoader != null;
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<String> classPaths = new ArrayList<>();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            if (resource.getProtocol().equals("jar")) {
                // 处理 JAR 文件
                try (JarFile jarFile = ((JarURLConnection) resource.openConnection()).getJarFile()) {
                    Enumeration<JarEntry> entries = jarFile.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry entry = entries.nextElement();
                        String entryName = entry.getName();
                        if (entryName.startsWith(path) && entryName.endsWith(".class")) {
                            // 提取类名并添加到类路径列表中
                            String className = entryName.replace('/', '.').substring(0, entryName.length() - 6);
                            classPaths.add(className);
                        }
                    }
                }
            } else {
                // 处理文件系统上的目录
                File dir = new File(resource.getFile());
                classPaths.addAll(findClassesInDirectory(dir, packageName));
            }
        }

        // 加载类
        Set<Class<?>> classes = new HashSet<>();
        for (String className : classPaths) {
            classes.add(Class.forName(className));
        }
        return classes;
    }

    private static List<String> findClassesInDirectory(File directory, String packageName) {
        List<String> classNames = new ArrayList<>();
        if (!directory.exists()) {
            return classNames;
        }
        File[] files = directory.listFiles();
        if (files == null) {
            return classNames;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                classNames.addAll(findClassesInDirectory(file, packageName + "." + file.getName()));
            } else if (file.getName().endsWith(".class")) {
                classNames.add(packageName + '.' + file.getName().substring(0, file.getName().length() - 6));
            }
        }
        return classNames;
    }

}